Skip to content

feat: add HMR support for pion components via Vite plugin#98

Draft
cristinecula wants to merge 1 commit into
mainfrom
feat/hmr-support
Draft

feat: add HMR support for pion components via Vite plugin#98
cristinecula wants to merge 1 commit into
mainfrom
feat/hmr-support

Conversation

@cristinecula

Copy link
Copy Markdown
Contributor

Summary

  • Add hot module replacement infrastructure that enables swapping pion component renderers on live DOM instances without full page reloads
  • Add Vite plugin that automatically detects pion component files and injects HMR accept handlers
  • Hook state (useState, useReducer, etc.) is preserved across hot replacements

Architecture

The implementation has three parts:

1. HMR Runtime (src/hmr.ts)

  • Component registry mapping tag names → { renderer, elementClass, instances }
  • enableHMR() patches customElements.define to intercept pion component registrations
  • First define call: registers normally + tracks in registry
  • Subsequent define calls (same tag): extracts new renderer via rendererSymbol, swaps it on all live instances via _scheduler.renderer, triggers _scheduler.update()

2. Component integration (src/component.ts, src/symbols.ts)

  • rendererSymbol stored on each Element class so the HMR runtime can extract it
  • hmrTagSymbol set on prototypes so instances self-register in connectedCallback/disconnectedCallback
  • Instance tracking only activates when isHMRActive() is true (zero overhead in production)

3. Vite Plugin (src/vite-plugin.ts)

  • transformIndexHtml: injects <script type="module"> preamble that calls enableHMR() before app code loads
  • transform: detects files matching customElements.define('tag', component(...)) and appends import.meta.hot.accept()
  • Only active during vite serve (no effect on production builds)

Usage

// vite.config.ts
import { defineConfig } from 'vite';
import pion from '@pionjs/pion/vite-plugin';

export default defineConfig({
  plugins: [pion()],
});

No changes needed in component files.

Known limitations

  • Only works with pion component() — Polymer/legacy components are not hot-replaceable
  • observedAttributes changes during HMR won't take effect (read once by the browser at define time)
  • Source maps from the Vite plugin transform are not yet generated

Tests

Added test/hmr.test.ts covering:

  • Component registration in HMR registry
  • Instance tracking via connected/disconnected callbacks
  • Renderer hot replacement with re-render
  • Hook state preservation across replacements
  • Graceful handling of no-instance and re-define scenarios
  • Multiple instance updates

Add hot module replacement infrastructure that enables swapping pion
component renderers on live DOM instances without full page reloads.

- Add HMR runtime (src/hmr.ts) with component registry, instance
  tracking, and renderer hot-swap via patched customElements.define
- Add Vite plugin (src/vite-plugin.ts) that injects enableHMR() preamble
  and appends import.meta.hot.accept() to component files
- Modify component.ts to store renderer on Element class via Symbol and
  track/untrack instances in connected/disconnected callbacks
- Add rendererSymbol and hmrTagSymbol to symbols.ts
- Add package.json exports for ./hmr and ./vite-plugin subpaths
- Add HMR test suite covering registration, instance tracking, renderer
  replacement, state preservation, and re-define handling
@netlify

netlify Bot commented Feb 16, 2026

Copy link
Copy Markdown

Deploy Preview for pionjs ready!

Name Link
🔨 Latest commit 0f4c32f
🔍 Latest deploy log https://app.netlify.com/projects/pionjs/deploys/6992b9fc895b2f000896d72d
😎 Deploy Preview https://deploy-preview-98--pionjs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@changeset-bot

changeset-bot Bot commented Feb 16, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 0f4c32f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant